package lyc.springcloud.zuul.lycspringcloudzuul.filter;

import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lyc.springcloud.zuul.lycspringcloudzuul.utils.CommonResClass;
import lyc.springcloud.zuul.lycspringcloudzuul.utils.JwtUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class UserAccessFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext context = RequestContext.getCurrentContext();
        return context.sendZuulResponse() && resetShouldFilter(context.getRequest().getRequestURI());
    }

    @SneakyThrows
    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        HttpServletResponse response = context.getResponse();
        String token = request.getHeader("web-token");

        // 校验token是否为空
        if(StringUtils.isEmpty(token)) {
            failureAuthorization(context, 401, "token为空，请退出重新登录!");
        }

        // 校验token是否过期 (jjwt的parser()方法解析token，会抛出异常)
        Map parseToken = null;
        try {
            parseToken = JwtUtil.parseToken(request);
            log.info("网关解析token:{}", parseToken);
        } catch (Exception e) {
            failureAuthorization(context, 402, "token已过期，请退出重新登录!");
            log.error("网关token解析异常:", e);
        }

        // 刷新token
        try {
            String refreshedToken;
            Map<String, Object> tokenSubject = new HashMap<String, Object>();
            tokenSubject.put("userId", parseToken.get("userId"));
            tokenSubject.put("username", parseToken.get("username"));
            tokenSubject.put("roleInfo", parseToken.get("roleInfo"));
            refreshedToken = JwtUtil.refreshToken(tokenSubject);
            log.info("网关刷新的token:{}", token);
            response.setHeader("web-token", refreshedToken);
        } catch (Exception e) {
            log.error("网关刷新token异常", e);
        }

        return null;
    }

    private Boolean resetShouldFilter(String requestUrl) {
        // login和register放行
        if(requestUrl.contains("/register") || requestUrl.contains("/login")) {
            return false;
        }
        // 其他不需要token校验的api
        if(requestUrl.contains("/test") || requestUrl.contains("/noToken/xxx")) {
            return false;
        }
/*        // 临时放开
        if(requestUrl.contains("/lyc-admin")) {
            return false;
        }*/
        return true;
    }

    // 授权失败处理fun
    private void failureAuthorization(RequestContext requestContext, int httpStatusCode, String failureMsg) {
        requestContext.setSendZuulResponse(false);
        requestContext.setResponseStatusCode(httpStatusCode);
        requestContext.getResponse().setContentType("application/json;charset=UTF-8");
        requestContext.setResponseBody(JSON.toJSONString(CommonResClass.failure(failureMsg)));
    }
}
